/**
开始学习反射（reflect）相关的概念，了解反射的类型对象和反射的值对象。
用学到的知识实现下面的题目：
将结构体数据保存为JSON格式的文本数据并输出到文件中。
保证代码结构严谨，无报错，不崩溃。
 */
package main

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"os"
)

type User struct {
	Id int
	Name string
	Age int
}

func (this User) String () {
	fmt.Println("User:", this.Id, this.Name, this.Age)
}

func Info (o interface{}) {
	//获取Value信息
	v := reflect.ValueOf(o)
	fmt.Println(v)
	//通过Value获取Type
	t := v.Type()
	fmt.Println(t, t.Name())
	//类型名称
	fmt.Println("Type:", t.Name())

	//访问接口字段名、字段类型和字段值信息
	fmt.Println("Fields:")
	var json = "{"
	for i :=0 ; i < t.NumField(); i++ {
		field := t.Field(i)
		value := v.Field(i).Interface()

		//类型查询
		switch value := value.(type) {
		case int:
			json += "\"" +field.Name + "\":" + strconv.Itoa(value) + ","
			fmt.Printf(" %6s: %v = %d\n", field.Name, field.Type, value)
		case string:
			json += "\"" +field.Name + "\":" + value + ","
			fmt.Printf(" %6s: %v = %s\n", field.Name, field.Type, value)
		default:
			fmt.Printf(" %6s: %v = %s\n", field.Name, field.Type, value)
		}
		if i == t.NumField() - 1 {
			json = strings.TrimRight(json, ",")
		}
	}
	json += "}"


	file, error := os.OpenFile("json.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
	if error != nil {
		fmt.Println(error)
		os.Exit(0)
	}
	file.WriteString(json+"\r\n")
	file.Close()
}

func main() {
	u := User{10,"Tom", 20}
	Info(u)
}